home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et3_0-a1.lha / et3 / src / Document.C < prev    next >
C/C++ Source or Header  |  1992-07-10  |  8KB  |  393 lines

  1. #ifdef __GNUG__
  2. #pragma implementation
  3. #endif
  4.  
  5. #include "Document.h"
  6.  
  7. #include "Class.h"
  8. #include "ImageItem.h"
  9. #include "FileDialog.h"
  10. #include "System.h"
  11. #include "CommandProcessor.h"
  12. #include "WindowSystem.h"
  13. #include "Env.h"
  14. #include "ProgressDialog.h"
  15. #include "OrdColl.h"
  16. #include "CLib.h"
  17. #include "Data.h"
  18. #include "MenuBar.h"
  19. #include "Menu.h"
  20. #include "CmdNo.h"
  21. #include "String.h"
  22. #include "Application.h"
  23. #include "Alert_e.h"
  24.  
  25. extern SmartBitmap gFileIcon;
  26.  
  27. static FileDialog *loadDialog, *saveDialog;
  28.  
  29. ONEXIT(Document)
  30. {
  31.     SafeDelete(loadDialog);
  32.     SafeDelete(saveDialog);
  33. }
  34.  
  35. static int untitledCnt;
  36.  
  37. //---- Document ----------------------------------------------------------------
  38.  
  39. NewAbstractMetaImpl(Document,Manager, (T(docType), TP(docData)));
  40.  
  41. Document::Document(const Symbol &dt)
  42. {
  43.     docType= dt;
  44.     docData= new FileData(form("untitled.%d", untitledCnt++), TRUE);
  45.     Manager::SetName(GetBaseName());
  46.     SetOnDismiss(eMgrIconize);
  47. }
  48.  
  49. Document::~Document()
  50. {
  51.     SafeDelete(docData);
  52. }
  53.  
  54. CommandProcessor *Document::MakeCmdProcessor()
  55. {
  56.     int n= Env::GetValue("Document.UndoLevel", 1);
  57.     if (n == 1)
  58.     return new CommandProcessor1;
  59.     if (n > 100)
  60.     return new CommandProcessorN;
  61.     return new CommandProcessor10(n);
  62. }
  63.     
  64. FileDialog *Document::MakeFileDialog(FileDialogType)
  65. {
  66.     return gApplication->MakeFileDialog();
  67. }
  68.  
  69. char *Document::GetBaseName()
  70. {
  71.     return docData->ShortName();
  72. }
  73.  
  74. int Document::UniqueId()
  75. {
  76.     return docData->UniqueId();
  77. }
  78.  
  79. bool Document::IsUntitled()
  80. {
  81.     return docData->IsUntitled();
  82. }
  83.  
  84. bool Document::IsConverted()
  85. {
  86.     if (docType == cDocTypeAscii && docData->IsAscii())
  87.     return FALSE;
  88.     return docData->Type() != docType;
  89. }
  90.  
  91. void Document::SetData(Data *fd)
  92. {
  93.     if (fd && fd != docData) {
  94.     SafeDelete(docData);
  95.     docData= (Data*) fd->DeepClone();
  96.     }
  97.     Manager::SetName(GetBaseName());
  98. }
  99.  
  100. VObject *Document::DoMakeIconContent()
  101. {
  102.     return DoMakeIcon(GetName());
  103. }
  104.  
  105. VObject *Document::DoMakeIcon(char*)
  106. {
  107.     return new ImageItem(gFileIcon, 13);
  108. }
  109.  
  110. //---- Menus -------------------------------------------------------------------
  111.  
  112. MenuBar *Document::DoMakeMenuBar()
  113. {
  114.     MenuBar *mb= new MenuBar;
  115.     mb->AddMenu(MakeMenu(cHELPMENU));
  116.     mb->AddMenu(MakeMenu(cFILEMENU));
  117.     mb->AddMenu(MakeMenu(cEDITMENU));
  118.     mb->AddMenu(MakeMenu(cAPPMENU));
  119.     return mb;
  120. }
  121.  
  122. Menu *Document::MakeMenu(int menuId)
  123. {
  124.     Menu *m;
  125.     
  126.     switch (menuId) {
  127.     case cFILEMENU:
  128.     m= new Menu(cFILEMENU, "File");
  129.     m->AppendItems( 
  130.         "New@N",        cNEW,
  131.         "Open ...@O",   cOPEN,
  132.         "-",
  133.         "Load ...@L",   cLOAD,
  134.         "Save@S",       cSAVE,
  135.         "Save As ...",  cSAVEAS,
  136.         "Revert",       cREVERT,
  137.         "Close",        cCLOSE,
  138.         "-",
  139.         "Print ...@P",  cPRINT,
  140.         "-",
  141.         "Quit@Q",       cQUIT,
  142.         0);
  143.     break;
  144.     
  145.     default:
  146.     m= Manager::MakeMenu(menuId);
  147.     }
  148.     return m;
  149. }
  150.  
  151. void Document::DoSetupMenu(Menu *m)
  152. {
  153.     Manager::DoSetupMenu(m);
  154.     GetCmdP()->DoSetupMenu(m);
  155.     if (Modified()) {
  156.     m->EnableItem(cSAVE);
  157.     if (!IsUntitled())
  158.         m->EnableItem(cREVERT);
  159.     }
  160.     m->EnableItems(cLOAD, cSAVEAS, cPRINT, 0);
  161. }
  162.  
  163. Command *Document::DoMenuCommand(int cmd)
  164. {
  165.     switch(cmd) {
  166.     case cSAVE:     Save();     break;
  167.     case cSAVEAS:   SaveAs();   break;
  168.     case cLOAD:     Load();     break;
  169.     case cREVERT:   Revert();   break;
  170.     case cCLOSE:    Close();   break;
  171.     default:
  172.     return Manager::DoMenuCommand(cmd);
  173.     }
  174.     return gNoChanges;
  175. }
  176.  
  177. void Document::CollectParts(Collection *col)
  178. {
  179.     Manager::CollectParts(col);
  180.     if (docData)
  181.     col->Add(docData);
  182. }
  183.  
  184. void Document::ExtCommand(int c, char *req, char *args, int l, char *&rc, int &rl)
  185. {
  186.     if (strcmp(req, "load") == 0)
  187.     Load(args);
  188.     else if (strcmp(req, "save") == 0)
  189.     Save();
  190.     else
  191.     Manager::ExtCommand(c, req, args, l, rc, rl);
  192. }
  193.  
  194. bool Document::Modified()
  195. {
  196.     return GetCmdP()->Modified();
  197. }
  198.  
  199. bool Document::SavedChanges()
  200. {
  201.     if (Modified()) {
  202.     switch (ShowAlert(eAlertCaution, "Save changes to @B%s @P?", docData->Name())) {
  203.     case cIdYes:
  204.         if (Save())
  205.         return TRUE;
  206.         return FALSE;        // save cancelled -> cancel all
  207.     case cIdNo:
  208.         GetCmdP()->Finish();
  209.         return TRUE;
  210.     case cIdCancel:
  211.         return FALSE;
  212.     }
  213.     }
  214.     return TRUE;
  215. }
  216.  
  217. bool Document::Load(char *filename, bool unique)
  218. {
  219.     if (filename) {
  220.     Data *d= new FileData(filename);
  221.     bool b= LoadData(d, unique);
  222.     delete d;
  223.     return b;
  224.     }
  225.     return LoadData(0, unique);
  226. }
  227.  
  228. bool Document::LoadData(Data *data, bool unique)
  229. {
  230.     if (! SavedChanges())
  231.     return FALSE;
  232.  
  233.     if (data == 0) {
  234.     if (loadDialog == 0)
  235.         loadDialog= MakeFileDialog(eFDTypeRead);
  236.     if (loadDialog->ShowInWindow(eFDRead, GetWindow(), this) != cIdOk)
  237.         return FALSE;
  238.     data= loadDialog->GetData();
  239.     }
  240.  
  241.     if (CanLoad(data)) {
  242.     if (data->UniqueId() == 0) {
  243.         ShowAlert(eAlertNote, "something wrong with @B%s @P\n%s", data->Name(),
  244.                             gSystem->GetErrorStr());
  245.         return FALSE;
  246.     }
  247.     
  248.     if (unique) {
  249.         Document *doc= gApplication->FindDocument((int)data->UniqueId());
  250.         if (doc && !DoFileIsAlreadyOpen(doc, data->FullName()))
  251.         return FALSE;
  252.     }
  253.     
  254.     AboutToLoad(data);
  255.  
  256.     SetData(data);
  257.     
  258.     gProgress->Start(form("Reading: %s", GetBaseName()), data->SizeHint());
  259.     DoReadData(data);
  260.     gProgress->Stop();
  261.  
  262.     gWindowSystem->Update();
  263.     } else
  264.     gApplication->OpenDocument(data->FullName());
  265.  
  266.     return TRUE;
  267. }
  268.  
  269. void Document::AboutToLoad(Data*)
  270. {
  271. }
  272.  
  273. bool Document::Close()   // return TRUE if OK
  274. {
  275.     if (IsOpen()) {
  276.     if (SavedChanges())
  277.         return Manager::Close();
  278.     return TRUE;
  279.     }
  280.     return FALSE;
  281. }
  282.  
  283. bool Document::Save()
  284. {
  285.     if (Modified() && (IsUntitled() || IsConverted()))
  286.     return SaveAs();
  287.  
  288.     if (! Modified()) {
  289.     ShowAlert(eAlertNote, "No changes since last save");
  290.     return TRUE;
  291.     }
  292.  
  293.     if (! docData->IsWritable()) {
  294.     ShowAlert(eAlertNote, "Document @B%s @Pis not writable\n%s",
  295.                     docData->Name(), gSystem->GetErrorStr());
  296.     return FALSE;
  297.     }
  298.  
  299.     if (Env::GetValue("Document.MakeBackup", FALSE))
  300.     MakeBackup(docData->FullName(), 0);
  301.  
  302.     Store();
  303.     
  304.     return TRUE;
  305. }
  306.  
  307. bool Document::SaveAs()
  308. {
  309.     if (saveDialog == 0)
  310.     saveDialog= MakeFileDialog(eFDTypeWrite);
  311.  
  312.     if (saveDialog->ShowInWindow(eFDWrite, GetWindow(), this) == cIdOk) {
  313.     SetData(saveDialog->GetData());
  314.     Store();
  315.     return TRUE;
  316.     }
  317.     return FALSE;
  318. }
  319.  
  320. void Document::Revert()
  321. {
  322.     if (Modified() && ShowAlert(eAlertCaution, "Discard all changes of @B%s @P?", 
  323.                             GetBaseName()) == cIdYes) {
  324.     GetCmdP()->Finish();
  325.     Load(docData->FullName(), FALSE);
  326.     }
  327. }
  328.  
  329. //---- Load/Store Documents -----------------------------------------------------
  330.  
  331. void Document::MakeBackup(char *path, char*)
  332. {
  333.     gSystem->Rename(path, form("%s%%", path));
  334. }
  335.  
  336. bool Document::CanLoad(Data *data)
  337. {
  338.     if (GetDocumentType() == data->Type())
  339.     return TRUE;
  340.     if (GetDocumentType() == cDocTypeAscii && data->IsAscii())
  341.     return TRUE;
  342.     return FALSE;
  343. }
  344.  
  345. bool Document::DoFileIsAlreadyOpen(Document *shown, char *name)
  346. {
  347.     ShowAlert(eAlertNote, "Document @B%s @Pis already open", name);
  348.     if (shown != this)
  349.     shown->Show();
  350.     return FALSE;
  351. }
  352.  
  353. void Document::Store()
  354. {
  355.     GetCmdP()->Finish();
  356.     
  357.     gProgress->Start(form("Writing: %s", GetBaseName()), 1000000);
  358.     if (!docData->IsUntitled()) {
  359.     gSystem->Rename(docData->FullName(), form("%s%%", docData->FullName()));
  360.     }
  361.  
  362.     OStream to(docData->GetStreamBufForWriting(), TRUE);
  363.     if (DoWrite(to, docData)) {
  364.     if (!Env::GetValue("Document.MakeBackup", FALSE)) {
  365.         CLib::Unlink(form("%s%%", docData->FullName()));
  366.     }
  367.     }
  368.     gProgress->Stop();
  369. }
  370.  
  371. bool Document::DoWrite(OStream& to, Data*)
  372. {
  373.     to << cMagic SP << docType SP << gApplication->ProgramName() NL;
  374.     return TRUE;
  375. }
  376.  
  377. bool Document::DoReadData(Data *data)
  378. {   
  379.     IStream from(data->GetStreamBufForReading(), 0, TRUE);
  380.     return DoRead(from, data);
  381. }
  382.  
  383. bool Document::DoRead(IStream &from, Data*)
  384. {
  385.     char c;
  386.     // overread magic cookie
  387.     while (from.get(c))
  388.     if (c == '\n')
  389.         break;
  390.     return TRUE;
  391. }
  392.  
  393.